/**
 * @file LogStream.cpp
 * @brief 日志流实现
 * @author Enterprise Logger Team
 * @date 2024
 */

#include "LogStream.h"
#include <algorithm>
#include <cstdio>
#include <cinttypes>

namespace logger {

// 静态断言检查大小
static_assert(sizeof(detail::FixedBuffer<detail::kSmallBufferSize>) == detail::kSmallBufferSize + sizeof(char*),
              "FixedBuffer size check");

namespace {
    const char digits[] = "0123456789";
    const char digitsHex[] = "0123456789ABCDEF";
}

// double类型格式化
LogStream& LogStream::operator<<(double v) {
    if (format_state_ == FormatState::FORMATTING) {
        format_args_.emplace_back(v);
        checkAndFlushFormat();
    } else {
        if (buffer_.avail() >= kMaxNumericSize) {
            char buf[kMaxNumericSize];
            int len = snprintf(buf, sizeof(buf), "%.12g", v);
            buffer_.append(buf, len);
        }
    }
    return *this;
}

// 指针格式化
LogStream& LogStream::operator<<(const void* p) {
    uintptr_t v = reinterpret_cast<uintptr_t>(p);
    if (buffer_.avail() >= kMaxNumericSize) {
        char* buf = buffer_.current();
        buf[0] = '0';
        buf[1] = 'x';
        size_t len = convertHex(buf + 2, v);
        buffer_.add(len + 2);
    }
    return *this;
}

// 十六进制转换
size_t LogStream::convertHex(char* buf, uintptr_t value) {
    uintptr_t i = value;
    char* p = buf;

    do {
        int lsd = static_cast<int>(i % 16);
        i /= 16;
        *p++ = digitsHex[lsd];
    } while (i != 0);

    *p = '\0';
    std::reverse(buf, p);

    return p - buf;
}

// Fmt模板特化实现
template<typename T>
Fmt::Fmt(const char* fmt, T val) {
    static_assert(std::is_arithmetic<T>::value, "Fmt requires arithmetic type");
    
    // 使用snprintf格式化
    length_ = snprintf(buf_, sizeof(buf_), fmt, val);
    if (length_ < 0) {
        length_ = 0;
    } else if (length_ >= static_cast<int>(sizeof(buf_))) {
        length_ = sizeof(buf_) - 1;
    }
}

// 显式实例化常用类型
template Fmt::Fmt(const char* fmt, char);
template Fmt::Fmt(const char* fmt, short);
template Fmt::Fmt(const char* fmt, unsigned short);
template Fmt::Fmt(const char* fmt, int);
template Fmt::Fmt(const char* fmt, unsigned int);
template Fmt::Fmt(const char* fmt, long);
template Fmt::Fmt(const char* fmt, unsigned long);
template Fmt::Fmt(const char* fmt, long long);
template Fmt::Fmt(const char* fmt, unsigned long long);
template Fmt::Fmt(const char* fmt, float);
template Fmt::Fmt(const char* fmt, double);

}  // namespace logger
